package bus

import (
	"fmt"
	"time"

	"git.oschina.net/antlinker/antevent/server/evtlog"

	"github.com/antlinker/sdk/asapi"
	"github.com/dchest/captcha"
	"github.com/dgrijalva/jwt-go"
	"github.com/pkg/errors"
)

// Auth 认证服务
type Auth interface {
	// 获取登录令牌
	LoginToken(userName, pwd string) (tokenString string, err error)
	//更新用户令牌
	RefreshToken(tokenString string) (newTokenString string, err error)

	GetCaptchaID() string
	Verfiy(tokenString string) (r bool, err error)
	CreProdToken() (tokenString string, err error)
}

type auth struct {
	jwtSignedKey []byte
	service      string
}

// CreateAuth 创建认证业务
func CreateAuth(jwtSignedKey, service string) Auth {
	return &auth{jwtSignedKey: []byte(jwtSignedKey), service: service}
}

// TokenClaims 用户令牌信息
type TokenClaims struct {
	jwt.StandardClaims
	AccessToken  string `json:"at,omitempty"`
	RefreshToken string `json:"rt,omitempty"`
	UserID       string `json:"uid,omitempty"`
}

func (a auth) GetCaptchaID() string {
	return captcha.NewLen(4)
}

// LoginToken 获取登录令牌
func (a auth) LoginToken(userName, pwd string) (tokenString string, err error) {
	tokenInfo, vresult := asapi.UserLoginToken(userName, pwd, a.service)
	if vresult != nil {
		err = errors.New(vresult.Error())
		return
	}

	// // 检查是否是管理员用户
	// isAdmin, err := store.GetIUser().CheckIsAdmin(tokenInfo.UserID)
	// if err != nil {
	// 	return
	// } else if !isAdmin {
	// 	err = errors.New("不是管理用户")
	// 	return
	// }

	evtlog.Info(fmt.Sprintf("登录用户：%s - %s - %s", tokenInfo.UserID, tokenInfo.AccessToken, tokenInfo.RefreshToken))

	// 生成访问令牌
	tc := &TokenClaims{}

	currentTime := time.Now()
	tc.IssuedAt = currentTime.Unix()
	tc.ExpiresAt = currentTime.Add(time.Second * time.Duration(tokenInfo.Expires)).Unix()
	//tc.ExpiresAt = currentTime.Add(time.Hour * 24 * 7).Unix()
	tc.AccessToken = tokenInfo.AccessToken
	tc.UserID = tokenInfo.UserID
	tc.RefreshToken = tokenInfo.RefreshToken

	jtoken := jwt.NewWithClaims(jwt.SigningMethodHS256, tc)

	tokenString, err = jtoken.SignedString(a.jwtSignedKey)

	return
}

// ParseToken 解析用户令牌
func (a auth) ParseToken(tokenString string) (userID, atoken, rtoken string, err error) {
	token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) {
		return a.jwtSignedKey, nil
	})

	if err != nil {
		err = errors.Wrap(err, "解析令牌失败")
		return
	} else if !token.Valid {
		err = errors.New("invalid token")
		return
	}

	claims, ok := token.Claims.(*TokenClaims)
	if !ok {
		err = errors.New("invalid claims")
		return
	}

	// 验证令牌的有效性
	// vuid, _, vresult := asapi.VerifyToken(claims.AccessToken)
	// if vresult != nil {
	// 	err = errors.New(vresult.Error())
	// 	return
	// }

	// userID = vuid
	atoken = claims.AccessToken
	rtoken = claims.RefreshToken
	userID = claims.AccessToken

	return
}

// RefreshToken 更新用户令牌
func (a auth) RefreshToken(tokenString string) (newTokenString string, err error) {
	_, _, rtoken, err := a.ParseToken(tokenString)
	if err != nil {
		return
	}

	tokenInfo, vresult := asapi.UserRefreshToken(rtoken)
	if vresult != nil {
		err = errors.Wrap(vresult, "更新令牌失败")
		return
	}

	// 生成访问令牌
	tc := &TokenClaims{}

	currentTime := time.Now()
	tc.IssuedAt = currentTime.Unix()
	tc.ExpiresAt = currentTime.Add(time.Second * time.Duration(tokenInfo.Expires)).Unix()
	tc.AccessToken = tokenInfo.AccessToken
	tc.RefreshToken = rtoken

	jtoken := jwt.NewWithClaims(jwt.SigningMethodHS256, tc)
	newTokenString, err = jtoken.SignedString(a.jwtSignedKey)

	return
}

// RefreshToken 更新用户令牌
func (a auth) Verfiy(tokenString string) (r bool, err error) {
	_, atoken, _, err := a.ParseToken(tokenString)
	if err != nil {
		err = errors.Wrap(err, "解析令牌失败")
		return
	}
	_, _, result := asapi.VerifyToken(atoken)
	if result == nil {
		r = true
	} else {
		err = errors.Wrap(result, "检验令牌失败")
	}
	return
}

// LoginToken 获取登录令牌
func (a auth) CreProdToken() (tokenString string, err error) {

	tokenInfo, vresult := asapi.GetToken()
	if vresult != nil {
		err = errors.New(vresult.Error())
		return
	}

	// // 检查是否是管理员用户
	// isAdmin, err := store.GetIUser().CheckIsAdmin(tokenInfo.UserID)
	// if err != nil {
	// 	return
	// } else if !isAdmin {
	// 	err = errors.New("不是管理用户")
	// 	return
	// }

	// 生成访问令牌
	tc := &TokenClaims{}

	currentTime := time.Now()
	tc.IssuedAt = currentTime.Unix()
	//tc.ExpiresAt = currentTime.Add(time.Hour * 24 * 7).Unix()
	tc.AccessToken = tokenInfo

	jtoken := jwt.NewWithClaims(jwt.SigningMethodHS256, tc)

	tokenString, err = jtoken.SignedString(a.jwtSignedKey)

	return
}
